#ifndef __SAMPLES_H__
#define __SAMPLES_H__

////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////

#include <vector>
#include <string>

////////////////////////////////////////////////////////////////////////////////
// Namespaces
////////////////////////////////////////////////////////////////////////////////

namespace Toolkit {

////////////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////////////

/**
 *  This class defines a samples handler which can load them from files
 */
class SamplesHandler {

	friend class SampleSet;

	public:

		// Constructor
		SamplesHandler(const std::string & = "");

		/// Copy constructor
		SamplesHandler(const SamplesHandler &);

		/// Affectation operator
		SamplesHandler & operator = (const SamplesHandler &);

		/// Returns the samples
		const std::vector< std::vector<std::string> > & GetSamplesData() const { return this->samples_data; }

		/// Returns the samples
		std::vector< std::vector<std::string> > & SamplesData() { return this->samples_data; }

		/// Returns the sample size
		const int GetDataSize() const { return this->data_size; }

		/// Returns the sample type
		const std::string & GetDataType() const { return this->data_type; }

		/// Load samples from a file
		void LoadFromFile(const std::string &);

		/// Remove element at the given index
		void RemoveAt(const unsigned int);

		/// Clear all data
		void Clear();

	protected:

		/// Samples
		std::vector< std::vector<std::string> > samples_data;

		/// Sample size
		int data_size;

		/// Sample type
		std::string data_type;

};

/**
 *  This class defines a sample set
 */
class SampleSet {

	public:

		/// Constructor
		SampleSet(const std::string & = "Set");

		/// Copy constructor
		SampleSet(const SampleSet &);

		/// Constructor from file
		SampleSet(std::istream &);

		/// Affectation operator
		SampleSet & operator = (const SampleSet &);

		/// Returns the name
		const std::string & GetName() const { return this->name; }

		/// Returns the name
		std::string & Name() { return this->name; }

		/// Returns the classification
		const std::vector<double> & GetClassification() const { return this->classification; }

		/// Sets the classification
		void SetClassification(const std::vector<double> & value) { this->classification = value; }

		/// Returns the samples
		const SamplesHandler & GetSamples() const { return this->samples; }

		/// Returns the results
		const std::vector< std::vector<double> > & GetSamplesResults() const { return this->samples_results; }

		/// Add samples from a file
		void AddSamplesFromFile(const std::string &);

		/// Clear all samples
		void ClearSamples();

		/// Remove samples at the given index
		void RemoveSamplesAt(unsigned int);

		/// Clear all samples results
		void ClearSamplesResults();

		/// Set result at the given index
		void SetSamplesResultsAt(unsigned int, const std::vector<double> &);

		/// Write
		void Write(std::ostream &);

		/// Read
		void Read(std::istream &);

		/// Export results
		void ExportResults(std::ostream &);

	protected:

		/// Set name
		std::string name;

		/// Classification
		std::vector<double> classification;

		/// Samples
		SamplesHandler samples;

		/// Results
		std::vector< std::vector<double> > samples_results;

};

////////////////////////////////////////////////////////////////////////////////
// Closing Namespaces
////////////////////////////////////////////////////////////////////////////////

}

////////////////////////////////////////////////////////////////////////////////

#endif
